from fastapi import APIRouter, Body, Depends, HTTPException, status, Query

from backend.mongo import get_database
from backend.models.instance import (
    CreateDwfInstanceModel,
    UpdateDwfInstanceModel,
    DwfInstanceInDB,
    PaginatedDwfInstanceResponse,
    INSTANCE_COLLECTION
)
from backend.services import instance as instance_service
from backend.services.exceptions import (
    InstanceAlreadyExistsError,
    InvalidObjectIdError,
    InstanceNotFoundError
)

router = APIRouter()


def get_instance_collection(db=Depends(get_database)):
    return db[INSTANCE_COLLECTION]


@router.post("/", response_model=DwfInstanceInDB, status_code=status.HTTP_201_CREATED)
async def create_instance(instance: CreateDwfInstanceModel = Body(...), collection=Depends(get_instance_collection)):
    try:
        return await instance_service.create(collection, instance)
    except InstanceAlreadyExistsError as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.get("/", response_model=PaginatedDwfInstanceResponse)
async def list_instances(
    collection=Depends(get_instance_collection),
    name: str = Query(None),
    page: int = Query(0, ge=0),
    page_size: int = Query(10, ge=1, le=100)
):
    return await instance_service.list_instances(collection, name, page, page_size)


@router.get("/{instance_id}", response_model=DwfInstanceInDB, summary="根据ID获取单个DWF实例")
async def get_instance(instance_id: str, collection=Depends(get_instance_collection)):
    try:
        return await instance_service.get_by_id(collection, instance_id)
    except (InvalidObjectIdError, InstanceNotFoundError) as e:
        raise HTTPException(status_code=400 if isinstance(e, InvalidObjectIdError) else 404, detail=str(e))


@router.put("/{instance_id}", response_model=DwfInstanceInDB)
async def update_instance(
        instance_id: str, instance_data: UpdateDwfInstanceModel = Body(...), collection=Depends(get_instance_collection)
):
    try:
        return await instance_service.update(collection, instance_id, instance_data)
    except (InvalidObjectIdError, InstanceNotFoundError, InstanceAlreadyExistsError, ValueError) as e:
        status_code = 400 if isinstance(e, (InvalidObjectIdError, InstanceAlreadyExistsError, ValueError)) else 404
        raise HTTPException(status_code=status_code, detail=str(e))


@router.delete("/{instance_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_instance(instance_id: str, collection=Depends(get_instance_collection)):
    try:
        await instance_service.delete(collection, instance_id)
    except (InvalidObjectIdError, InstanceNotFoundError) as e:
        raise HTTPException(status_code=400 if isinstance(e, InvalidObjectIdError) else 404, detail=str(e))
